package io;

import java.io.*;
//import java.nio.charset.StandardCharsets;

/**
 * 字符输入输出流
 * */
public class ReaderWriterStreamDemo {
    private String filename = "files/osw.txt";
    private String charsetName = "GBK";     // 编码格式

    /**
     * OutputStreamWriter
     * 继承Writer类
     * 是从字符流到字节流的桥接器：
     *      使用指定的字符集将写入其中的字符编码为字节。
     *      它使用的字符集可以通过名称指定，也可以明确指定，或者可以接受平台的默认字符集
     *
     *      每次调用write()方法都会导致在给定字符上调用编码转换器。
     *      生成的字节在写入底层输出流之前在缓冲区中累积。可以指定此缓冲区的大小，但默认情况下，它足够大，可用于大多数用途。
     *      请注意，传递给write()方法的字符不会被缓冲。
     * */
    public void testOutputStreamWriter() throws IOException {
        FileOutputStream fos = new FileOutputStream(filename);
//        OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
        OutputStreamWriter osw = new OutputStreamWriter(fos, charsetName);
        osw.write("我真的会谢！");
        osw.close();
    }

    /**
     * InputStreamReader
     * 继承Reader类
     * 是从字节流到字符流的桥接器：
     *      它使用指定的字符集读取字节并将它们解码为字符。
     *      它使用的字符集可以通过名称指定，也可以明确指定，或者可以接受平台的默认字符集。
     *      每次调用一个InputStreamReader的read()方法都可能导致从底层字节输入流中读取一个或多个字节。
     *      为了实现字节到字符的有效转换，可以从基础流中提取比满足当前读取操作所需的更多字节
     * */
    public void testInputStreamReader() throws IOException {
        InputStreamReader isr = new InputStreamReader(new FileInputStream(filename), charsetName);
        int ch = isr.read();    // 一次读取一个字符（两个字节），读到末尾返回 -1
        System.out.println((char) ch);
        while ((ch = isr.read()) != -1)
            System.out.print((char) ch);
        isr.close();
        System.out.println();
    }

    /**
     * BufferedWriter和BufferedReader
     * 缓冲字符流内部默认维护一个8k的char数组(长度可以创建缓冲流时修改)
     * 以块读写文本数据加快读写效率
     * */
    public void testBufferedWriterAndBufferedReader() throws IOException {
        BufferedWriter bw = new BufferedWriter(
                new OutputStreamWriter(new FileOutputStream(filename, true), charsetName));
        bw.write("缓冲字符流内部默认维护一个8k的char数组(长度可以创建缓冲流时修改)");
        bw.close();
        BufferedReader br = new BufferedReader(
                new InputStreamReader(new FileInputStream(filename), charsetName));
        String str = br.readLine();
        br.close();
        System.out.println(str);
    }

    /**
     * PrintWriter
     * 具有自动行刷新的缓冲字符输出流，特点是可以按行写出字符串，并且可以自动行刷新
     * 通过连接BufferedWriter实现的缓冲功能（内部自动连接）
     *
     * PrintWriter pw = new PrintWriter(new FileOutputStream(filename), true);
     * 第二参数表示自动行刷新，即每当调用pw.println()方法时立即将数据写入目标流（目的地）
     * */
    public void testPrintWriter() throws FileNotFoundException {
//        PrintWriter pw = new PrintWriter(filename);
        PrintWriter pw = new PrintWriter(new FileOutputStream(filename), true);
        pw.println("具有自动行刷新的缓冲字符输出流，特点是可以按行写出字符串，并且可以自动行刷新");
        pw.println("通过连接BufferedWriter实现的缓冲功能（内部自动连接）");
        pw.close();
    }

    public static void main(String[] args) throws IOException {
        ReaderWriterStreamDemo rws = new ReaderWriterStreamDemo();
        rws.testOutputStreamWriter();
        rws.testInputStreamReader();
        rws.testBufferedWriterAndBufferedReader();
        rws.testPrintWriter();
    }
}
